package site.wetsion.galio.sdk.utils;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import site.wetsion.galio.sdk.common.GalioOauthAccessToken;
import site.wetsion.galio.sdk.common.GalioOauthConstant;
import site.wetsion.galio.sdk.common.OauthClientContext;
import java.util.Date;
import java.util.Objects;

/**
 * 密码模式下获取token以及手动上下文设置token
 *
 * @author weixin
 * @version 1.0
 * @CLassName AuthPassowordProvider
 * @date 2019/4/28 5:04 PM
 */
public class AuthPassowordProvider {

    private static final Logger logger = LoggerFactory.getLogger(AuthPassowordProvider.class);

    /**
     * 获取token
     *
     * @param accessTokenUrl 获取token的URL,参考{@link site.wetsion.galio.sdk.common.GalioClientDetailsProperties#getAccessTokenUrl()}
     * @param username 用户
     * @param password 密码
     * @param clientId 客户端ID
     * @param clientSecret 客户端密钥
     * @return site.wetsion.galio.sdk.common.GalioOauthAccessToken
     **/
    public static GalioOauthAccessToken handle(String accessTokenUrl,
                                               String username,
                                               String password,
                                               String clientId,
                                               String clientSecret) {
        GalioOauthAccessToken accessToken = null;
        RestTemplate restTemplate = new RestTemplate();
        MultiValueMap<String, String> params= new LinkedMultiValueMap<>();
        params.add(GalioOauthConstant.GRANT_TYPE, GalioOauthConstant.PASSWORD);
        params.add(GalioOauthConstant.USERNAME, username);
        params.add(GalioOauthConstant.PASSWORD, password);
        params.add(GalioOauthConstant.CLIENT_ID, clientId);
        params.add(GalioOauthConstant.CLIENT_SECRET, clientSecret);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<String> responseEntity = null;
        try {
            responseEntity = restTemplate.postForEntity(
                    accessTokenUrl, entity, String.class);
            accessToken = JSON.parseObject(responseEntity.getBody(), GalioOauthAccessToken.class);
            if (Objects.nonNull(accessToken)) {
                accessToken.setExpiration(new Date(System.currentTimeMillis() + accessToken.getValidity() * 1000L));
            }
        } catch (Exception e) {
            logger.info("从远程auth获取认证失败: {}", e.getMessage());
        }
        return accessToken;
    }

    /**
     * 刷新token
     *
     * @param accessTokenUrl 刷新token的URL,等同于获取token的url参考{@link RmsClientDetailsProperties#getAccessTokenUrl()}
     * @param refreshToken 用于刷新的token
     * @param clientId 客户端ID
     * @param clientSecret 客户端密钥
     * @return com.dxy.data.rms.sdk.common.RmsOauthAccessToken
     **/
    public static GalioOauthAccessToken refreshToken(String accessTokenUrl,
                                             String refreshToken,
                                             String clientId,
                                             String clientSecret) {
        GalioOauthAccessToken refreshAccessToken = null;
        RestTemplate restTemplate = new RestTemplate();
        MultiValueMap<String, String> params= new LinkedMultiValueMap<>();
        params.add(GalioOauthConstant.GRANT_TYPE, GalioOauthConstant.REFRESH_TOKEN);
        params.add(GalioOauthConstant.REFRESH_TOKEN, refreshToken);
        params.add(GalioOauthConstant.CLIENT_ID, clientId);
        params.add(GalioOauthConstant.CLIENT_SECRET, clientSecret);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<String> responseEntity = null;
        try {
            responseEntity = restTemplate.postForEntity(
                    accessTokenUrl, entity, String.class);
            refreshAccessToken = JSON.parseObject(responseEntity.getBody(), GalioOauthAccessToken.class);
            if (Objects.nonNull(refreshAccessToken)) {
                refreshAccessToken.setExpiration(new Date(System.currentTimeMillis() + refreshAccessToken.getValidity() * 1000L));
            }
        } catch (Exception e) {
            logger.info("从远程auth刷新token失败: {}", e.getMessage());
        }
        return refreshAccessToken;
    }

    /**
     * 向上下文中设置accessToken
     *
     * @Param [context, accessToken]
     * @return void
     **/
    public static void receive(OauthClientContext context, GalioOauthAccessToken accessToken) {
        context.setAccessToken(accessToken);
    }
}
